package com.k.kc.cryptojava.rsa;

import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RSAKeyReader {

    /**
     * pem file to byteArray
     *
     * @param filename filename
     * @return result
     * @throws Exception e
     */
    private static byte[] pemFileToByte(String filename) throws Exception {
        try (PemReader pemReader = new PemReader(new InputStreamReader(
                new FileInputStream(filename)))) {
            PemObject pemObject = pemReader.readPemObject();
            return pemObject.getContent();
        }
    }

    /**
     * der file to byteArray
     *
     * @param filename filename
     * @return result
     * @throws Exception e
     */
    private static byte[] derFileToByte(String filename) throws Exception {
        return Files.readAllBytes(Paths.get(filename));
    }

    /**
     * openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt
     *
     * @param filename filename
     * @return result
     * @throws Exception e
     */
    public static PrivateKey readPrivateKeyDer(String filename) throws Exception {
        byte[] keyBytes = derFileToByte(filename);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(spec);
    }

    /**
     * openssl genrsa -out private_key.pem 2048
     *
     * @param filename filename
     * @return result
     * @throws Exception e
     */
    public static PrivateKey readPrivateKeyPem(String filename) throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        byte[] bytes = pemFileToByte(filename);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
     *
     * @param filename filename
     * @return result
     * @throws Exception e
     */
    public static PublicKey readPublicKeyDer(String filename) throws Exception {
        byte[] keyBytes = derFileToByte(filename);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }

    /**
     * openssl rsa -in private_key.pem -pubout -out public_key.pem
     *
     * @param filename filename
     * @return result
     * @throws Exception e
     */
    public static PublicKey readPublicKeyPem(String filename) throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        byte[] bytes = pemFileToByte(filename);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
        return keyFactory.generatePublic(keySpec);
    }

}
